﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tilver.Configuration;
using System.Threading;
using Tilver.Configuration.Logging;

namespace Tilver.Common
{
    internal class Logger : ILogger
    {
        public bool Enabled { get; set; }
        public bool UseThreadPool { get; set; }
        public List<AppenderItem> _appenders = new List<AppenderItem>();

        internal Logger(string categoryName = null)
        {
            LoggingConfigElement config = TilverSection.GetSection().LoggingConfig;
            if (string.IsNullOrEmpty(categoryName))
            {
                categoryName = config.DefaultCategory;
            }
            CategoryElement category = config.Categorys[categoryName];
            Enabled = category.Enabled;
            UseThreadPool = category.UseThreadPool;
            foreach (AppenderElement item in category.Appenders)
            {
                IAppender appender = AppenderFactory.Create(item.Name);
                _appenders.Add(new AppenderItem(appender, item.IsReplacer, item.ThrowException));
            }
        }
        public void Write(object message)
        {
            DoWrite(new LogEntry(message, typeof(string)));
        }

        public void Write<T>(T message)
        {
            DoWrite(new LogEntry(message, typeof(T)));
        }

        public void Write(Exception exception)
        {
            DoWrite(new LogEntry(exception));
        }

        private void DoWrite(LogEntry entry)
        {
            if (Enabled)
            {
                if (UseThreadPool)
                    ThreadPool.QueueUserWorkItem(new WaitCallback(DoWriteCallback), entry);
                else
                    DoWriteCallback(entry);
            }
        }
        private void DoWriteCallback(object state)
        {
            LogEntry entry = (LogEntry)state;
            bool isSuccessed = false;
            for (int i = 0; i < _appenders.Count; i++)
            {
                IAppender appender = _appenders[i].Appender;
                if (isSuccessed && _appenders[i].IsReplacer) { break; }
                try
                {
                    appender.DoAppend(entry);
                    isSuccessed = true;
                }
                catch
                {
                    if (_appenders[i].ThrowException) throw;
                }
            }
        }

    }

    

}
